/*******************************************************************************************
 FILE NAME: eQADC_OPS.c                                                                    
                                                                                           
 DESCRIPTION:                                                                              
 This file contains functions for the MPC5xxx to initialize and                            
 Perform conversion on a Fast and Slow eMIOS Triggered 4 Variable Queue on ADC0 and ADC1   
                                                                                           
===========================================================================================
 REV      AUTHOR         DATE          DESCRIPTION OF CHANGE                               
 ---      -----------    ----------    ---------------------                               
 2.3      J. Zeeff       08/Jan/2011   cleanup
 2.2      M.Eberhardt    21/Dec/2011   reconcile channels with gen 1 hardware              
 1.0      P. Schlein     16/Mar/10     Initial version-from Cookbook                       
*******************************************************************************************/

#include "config.h"
#include "system.h"

#ifndef MPC5602

#define EXTERN
#include "eQADC_OPS.h"

// CFIFO Status Constants
#define IDLE 0
#define WAIT 2
#define TRIGD 3

// CFIFO Trigger Mode Constants
#define DISABLE_Q 0x0
#define SW_TRIG_SS 0x1
#define LOW_GATED_EXT_SS 0x2
#define HIGH_GATED_EXT_SS 0x3
#define FALLING_EXT_SS 0x4
#define RISING_EXT_SS 0x5
#define FALL_OR_RISE_EXT_SS 0x6
#define SW_TRIG_CS 0x9          //Used for Phase 2 MM Test
#define LOW_GATED_EXT_CS 0xA
#define HIGH_GATED_EXT_CS 0xB
#define FALLING_EXT_CS 0xC
#define RISING_EXT_CS 0xD
#define FALL_OR_RISE_EXT_CS 0xE

#define EOQ 0x40000000          // terminates Cmd Q

/*******************************************************************************************
 FUNCTION     : init_ADC                                                                   
                                                                                           
 PURPOSE      :  Initilaize the eQADC in 2 Steps-1st-Prep ADCs, 2nd-Config for User        
 INPUT NOTES  :  ADC_CLK Speed                                                             
   12KRPM=200RPS=1200 Intake Events/sec (12 cylinders)                                     
   10 bit accuracy for ADC_CLK<=16mhz-see RM 19-3                                          
   @132mhz, divide by 22=ob01010, yields 375K Samples/sec-see RM Table 19-47, 18-89        
                                                                                           
 RETURN NOTES : None                                                                       
 WARNING      : S&B "MPC5554 Revealed" Used as Reference with Caution!                     
*******************************************************************************************/

void init_ADC(void)
{

    // Note:  eQADC Conversion Command Format-see RM 19.4.1.2.1, 19-50, pg 780                   
    //     First Byte=EOQ, PAUSE, "000", Ext BufrBit, BufrNmbr=ADC0 or 1, CALibration,           
    //     Second Byte=MsgTag for RFIFO-5, LngSmplTime-(4-5), TimeStmpReq-(6) ,                  
    //                           Format=Right Justified-(7),                                     
    //     Third Byte=Channel Number, Fourth Byte="0x00"                                         
    //     Internal Channels-40-44-see Revealed pg273                                            
    // Note: Timestamp affects, in eDMA-DLAST_SGA, BITER and CITER                               

    // Note: check Q sizes in eTPU_OPS.h - they must be exactly correct

    // FAST Queue-On ADC0  
    ADC_CmdQ0[0] =  0x02100000 | (16 << 8);        // No Time Stamp; Convert Channel 16, input =V_Batt, AN16
    ADC_CmdQ0[1] =  0x02100000 | (20 << 8) | EOQ;  // No Time Stamp; Convert Channel 20, input =TPS, AN20

    // SLOW Queue-On ADC1=B/N=1, RFIFO1=Msg Tag=1 
    ADC_CmdQ1[0] =  0x02100000 | (21 << 8);  // Disable Time Stamp; Convert Channel 21,input=CLT Sensor, AN21 
    ADC_CmdQ1[1] =  0x02100000 | (22 << 8);  // Disable Time Stamp; Convert Channel 4, input=IAT Sensor, AN22 
    ADC_CmdQ1[2] =  0x02100000 | (19 << 8);  // Disable Time Stamp; Convert Channel 19, input =MAP_2, AN19
    ADC_CmdQ1[3] =  0x02100000 | (17 << 8);  // Disable Time Stamp; Convert Channel 17, input =MAP_3, AN17
    ADC_CmdQ1[4] =  0x02100000 | (27 << 8);  // Disable Time Stamp; Convert Channel 27, input =P1, AN27
    ADC_CmdQ1[5] =  0x02100000 | (28 << 8);  // Disable Time Stamp; Convert Channel 28, input =P2, AN28
    ADC_CmdQ1[6] =  0x02100000 | (29 << 8);  // Disable Time Stamp; Convert Channel 29, input =P3, AN29
    ADC_CmdQ1[7] =  0x02100000 | (30 << 8);  // Disable Time Stamp; Convert Channel 30, input =P4, AN30
    ADC_CmdQ1[8] =  0x02100000 | (31 << 8);  // Disable Time Stamp; Convert Channel 31, input =P5, AN31
    ADC_CmdQ1[9] =  0x02100000 | (32 << 8);  // Disable Time Stamp; Convert Channel 32, input =P6, AN32
    ADC_CmdQ1[10] = 0x02100000 | (33 << 8);  // Disable Time Stamp; Convert Channel 33, input =P7, AN33
    ADC_CmdQ1[11] = 0x02100000 | (34 << 8);  // Disable Time Stamp; Convert Channel 34, input =P8, AN34
    ADC_CmdQ1[12] = 0x02100000 | (35 << 8);  // Disable Time Stamp; Convert Channel 35, input =P9, AN35
    ADC_CmdQ1[13] = 0x02100000 | (04 << 8);  // Disable Time Stamp; Convert Channel 4, input =P10, AN4
    ADC_CmdQ1[14] = 0x02100000 | (05 << 8);  // Disable Time Stamp; Convert Channel 5, input =P11, AN5
    ADC_CmdQ1[15] = 0x02100000 | (06 << 8);  // Disable Time Stamp; Convert Channel 6, input =P12, AN6
    ADC_CmdQ1[16] = 0x02100000 | (07 << 8);  // Disable Time Stamp; Convert Channel 7, input =P13, AN7
    ADC_CmdQ1[17] = 0x02100000 | (36 << 8);  // Disable Time Stamp; Convert Channel 36, input =P14, AN36
    ADC_CmdQ1[18] = 0x02100000 | (23 << 8);  // Disable Time Stamp; Convert Channel 36, input =O2_1_UA, AN23
    ADC_CmdQ1[19] = 0x02100000 | (24 << 8);  // Disable Time Stamp; Convert Channel 36, input =O2_1_UR, AN24
    ADC_CmdQ1[20] = 0x02100000 | (25 << 8);  // Disable Time Stamp; Convert Channel 36, input =O2_2_UA, AN25
    ADC_CmdQ1[21] = 0x02100000 | (26 << 8) | EOQ; // Disable Time Stamp; Convert Channel 36, input =O2_2_UR, AN26

    // Angle triggered Queue-On ADC2=B/N=1, RFIFO2=Msg Tag=1 
    ADC_CmdQ3[0] = 0x02100000 | (96 << 8);  	    // Disable Time Stamp ; Convert Channel 0/1, DAN0 knock
    ADC_CmdQ3[1] = 0x02100000 | (97 << 8) | EOQ;  	// Disable Time Stamp ; Convert Channel 2/3, DAN1 knock

    ADC_CmdQ5[0] = 0x02100000 | (18 << 8) | EOQ ;  	// Disable Time Stamp ; Convert Channel 18, MAP_1

    // Prepare the two ADCs for User Mode                                          

    // eQADC Module Configuration Register-see RM 19.3.2.1, 19-15, pg 745                        
    EQADC.MCR.R = 0x00000000;   // Synchronous Serial Interface-Disable; Debug-Disable

    // eQADC Null Message Send Format Register-see RM 19.3.2.2, 19-16, pg 746                    
    EQADC.NMSFR.R = 0x00000000;

    // eQADC Ext. Trigger Digital Filter Register-see RM 19.3.2.3, 19-17, pg 747                 
    EQADC.ETDFR.R = 0x00000000;

    // Note: MPC5634 RM indicates registers are 32 bit but they aren't

    // Six 16 bit eQADC CFIFO Control Registers -see RM 19.3.2.6, 19-20, pg 750 
    EQADC.CFCR[0].R = 0x0010;   // Software trigger,  Single Scan Enable = 0 (disabled)
                                // and CFIFO Invalidate bit = 0
   

    // Six eQADC Interrupt and DMA Control Registers - see RM 19.3.2.7, 19-22, pg 752          
    EQADC.IDCR[0].R = 0x0000;   // End of Queue Interrupt = 0
                                // Trigger Overrun Interrupt = 0
                                // Pause Interrupt = 0
    

    // CFIFO Underflow Interrupt = 0
    // CFIFO Fill Enable = 0
    // CFIFO Fill Select = Manual Mode = 0
    // RFIFO Overflow Interrupt = 0
    // RFIFO Drain = 0
    // RFIFO Drain Select = 0

    // Write Configuration Commands to Internal ADC Registers by using a CFIFO
    // -see RM 19.5.3, 19-113, pg 843                                                            

    // PUSH Four Commands Only into CFIFO Using eQADC CFIFO Push Register                        
    // -see RM 19.3.2.4, 19-18, pg 748                                                           
    // Note:  eQADC Write Configuration Format-see RM 19.4.1.2.1, 19-53, pg 783                  
    //     First Byte=EOQ, PAUSE Bit, "000", ExtBufrBit,BN bit=ADC0 or 1, R/W=1/0,               
    //     Next 2 Bytes=ADC Register High and Low Bytes,                                         
    //     Last Byte=ADC Register Address-see Table 19-25, 19-40, pg 770                         

    // eQADC ADC Time Stamp Control Register (0)-see RM 19.3.3.2, 19-43, pg 773                  
    EQADC.CFPR[0].B.CFPUSH = 0x00000802;        // ADC_TSCR = 0x0008=Clock divide=16     
    // 0x02 is the register address

    // eQADC ADC Time Base Counterl Register (0)-see RM 19.3.3.3, 19-44, pg 774                  
    EQADC.CFPR[0].B.CFPUSH = 0x00000003;        // ADC_TBCR = 0x0000=     
    // 0x03 is the register address

    // eQADC Initialize ADC0 Control Register-see RM 19.3.3.1, 19-40, pg 770                     
    EQADC.CFPR[0].B.CFPUSH = 0x00801201;        // 0x00=EOQ=0, PAUSE, EB, BufrNmbr=0, R/W
    // ADC0_CR = ADC Reg Hi/Lo=0x801F
    // ADC0 Enable-Ready to Start-bit 0=1, "000"
    // External Mux Disabled -bit 4=0, "000000"    
    // Prescaler =22=0b01010=0x12=375K Samples/sec
    // 0x01 is the register address

    // eQADC Initialize ADC1 Control Register-see RM 19.3.3.1, 19-40, pg 770                     
    EQADC.CFPR[0].B.CFPUSH = 0x82801F01;        // 0x82=EOQ=1, PAUSE, EB, BufrNmbr=1, R/W
    // ADC1_CR = ADC Reg Hi/Lo=0x801F
    // ADC0 Enable-Ready to Start-bit 0=1, "000"
    // External Mux Disabled -bit 4=0, "000000"    
    // Prescaler = 64=0b11111=0x1F=129K Samples/sec
    // 0x01 is the register address

    // Trigger CFIFO0 with Software Trigger, single Scan to Configure ADCx's
    // see RM 19.3.3.1, 19-40, pg 770
    EQADC.CFCR[0].B.MODE = 0x01;    // Left out of "Revealed"
    EQADC.CFCR[0].B.SSE = 0x01;

    // Wait for Triggered State end and Queue Done-see RM 19.3.2.11, 19-34, pg 764               
    // Wait for Triggered State end and Queue Done-see RM 19.3.2.8, 19-24, pg 754  
    while (EQADC.FISR[0].B.EOQF != 0x1) {}

    // Now, Clear the End Of Queue Flag (all 6) 
    EQADC.FISR[0].B.EOQF = 0x1;
    EQADC.FISR[1].B.EOQF = 0x1;
    EQADC.FISR[2].B.EOQF = 0x1;
    EQADC.FISR[3].B.EOQF = 0x1;
    EQADC.FISR[4].B.EOQF = 0x1;
    EQADC.FISR[5].B.EOQF = 0x1;

    // Now, Disable Queue in Preparation for Queue Mode Change                                   
    // -see RM 19.5.4, 19-114, pg 844                                                            
    EQADC.CFCR[0].R = 0x0000;
    EQADC.CFCR[1].R = 0x0000;
    EQADC.CFCR[2].R = 0x0000;
    EQADC.CFCR[3].R = 0x0000;
    EQADC.CFCR[4].R = 0x0000;
    EQADC.CFCR[5].R = 0x0000;

    // Wait for Queues IDLE Before Changing to User Mode-see RM 19.3.2.11, 19-34, pg 764 
         
    while (EQADC.CFSR.B.CFS0 != 0x0) { }
    while (EQADC.CFSR.B.CFS1 != 0x0) { }
    while (EQADC.CFSR.B.CFS2 != 0x0) { }
    while (EQADC.CFSR.B.CFS3 != 0x0) { }
    while (EQADC.CFSR.B.CFS4 != 0x0) { }
    while (EQADC.CFSR.B.CFS5 != 0x0) { }

    // Invalidate Command Queue                                                                  
    EQADC.CFCR[0].B.CFINV = 1;
    EQADC.CFCR[1].B.CFINV = 1;
    EQADC.CFCR[2].B.CFINV = 1;
    EQADC.CFCR[3].B.CFINV = 1;
    EQADC.CFCR[4].B.CFINV = 1;
    EQADC.CFCR[5].B.CFINV = 1;

    // 6 eQADC Interrupt and DMA Control Registers -see RM 19.3.2.7, 19-22, pg 752                   
    // TODO Change to use bit fields
    EQADC.IDCR[0].R = 0x0303;   // 
    EQADC.IDCR[1].R = 0x0303;   //
    EQADC.IDCR[2].R = 0x0303;   // 
    EQADC.IDCR[3].R = 0x0303;   // 
    EQADC.IDCR[4].R = 0x0303;   // 
    EQADC.IDCR[5].R = 0x0303;   // 
    // CFIFO Underflow Interrupt = 0
    // CFIFO Fill Enable = 1
    // CFIFO Fill Select = 1, via eDMA
    // RFIFO Overflow Interrupt = 0
    // RFIFO Drain = 1
    // RFIFO Drain Select = 1, via eDMA

    // 6 eQADC CFIFO Control Registers (Note: 0-5 registers)-see RM 19.3.2.6, 19-20, pg 750       
    // Trigger CFIFO with Software Trigger, single Scan to Configure ADCx's                     
    // -see RM 19.3.3.1, 19-40, pg 770                                                           
    EQADC.CFCR[0].B.MODE = 0x5; // Rising Edge Ext.Trigger, Single Scan
    EQADC.CFCR[1].B.MODE = 0x5; // Rising Edge Ext.Trigger, Single Scan
    EQADC.CFCR[2].B.MODE = 0x0; // unused - disabled
    EQADC.CFCR[3].B.MODE = 0x0; // TODO re-enable for knock Rising Edge Ext.Trigger, Single Scan
    EQADC.CFCR[4].B.MODE = 0x0; // unused - disabled
    EQADC.CFCR[5].B.MODE = 0x5; // Rising Edge Ext.Trigger, Single Scan

    // Set single scan
    EQADC.CFCR[0].B.SSE = 0x01; // Single Scan Enable = 1, CFIFO Inval. bit = 0
    EQADC.CFCR[1].B.SSE = 0x01; // Single Scan Enable = 1, CFIFO Inval. bit = 0
    EQADC.CFCR[2].B.SSE = 0x01; // Single Scan Enable = 1, CFIFO Inval. bit = 0
    EQADC.CFCR[3].B.SSE = 0x01; // Single Scan Enable = 1, CFIFO Inval. bit = 0
    EQADC.CFCR[4].B.SSE = 0x01; // Single Scan Enable = 1, CFIFO Inval. bit = 0
    EQADC.CFCR[5].B.SSE = 0x01; // Single Scan Enable = 1, CFIFO Inval. bit = 0

}

#endif
